/**
 * Copyright (c) 2017 hadlinks, All Rights Reserved.
 */
package com.bugull.farm.core.enums;

import com.bugull.farm.core.utils.ByteUtil;

/**
 * Project Name: bugu-farm-household
 * Package Name: com.bugull.farm.core.enums 
 * ClassName: CommandEnum 
 * Function: TODO ADD FUNCTION.  
 * date: 2017/7/7 14:05
 * @author songwei (songw@hadlinks.com)
 * @since JDK 1.8 
 */
public enum CommandEnum {

    //长连接设备相关指令（机械/电控设备）
    CMD_DEV_BALANCE((byte)0x01, "设备请求工作服务器"),
    CMD_DEV_JOIN((byte)0x02, "长连接设备请求接入"),
    CMD_DEV_LOCATION((byte)0x03, "长连接设备位置信息上报"),
    CMD_DEV_SENSOR((byte)0x04, "长连接设备传感器信息上报"),
    CMD_DEV_TEMP_SET((byte)0x05, "长连接设备设置"),
    CMD_DEV_FLOW((byte)0x06, "长连接设备人流量上报"),
    CMD_DEV_FLOW_SWITCH((byte)0x07, "长连接设备人流量启停"),
    CMD_DEV_SWITCH((byte)0x08, "长连接设备启停"),
    CMD_DEV_HEARTBEAT((byte)0x0A, "长连接设备心跳"),
    CMD_DEV_QUERY((byte)0x0B, "长连接设备查询设置信息"),
    CMD_DEV_LOCATION_SET((byte)0x0C, "长连接设备位置信息上报间隔设置"),
    CMD_DEV_HEARTBEAT_NEW((byte)0x0D, "长连接设备省流量型心跳命令"),
    CMD_DEV_PARAM_SET((byte)0x0E, "长连接设备控制板参数设置"),
    CMD_DEV_PARAM_QUERY((byte)0x0F, "长连接设备控制板参数查询"),
    CMD_DEV_DEFROST_SWITCH((byte)0x10, "长连接设备化霜开关"),
    CMD_DEV_LIGHT_SWITCH((byte)0x11, "长连接设备照明开关"),
    CMD_DEV_UPLOAD_SET((byte)0xA4, "长连接设备图片上传时间设置"),
    CMD_DEV_UPLOAD_QUERY((byte)0xA5, "长连接设备图片上传时间查询"),
    CMD_DEV_UPLOAD_LAST((byte)0xA6, "长连接设备上传最近一次采集图片"),

    //短连接设备相关指令（存量模块）
    CMD_DEV_SHORTCONN_BALANCE((byte)0x31, "短连接设备请求工作服务器"),
    CMD_DEV_SHORTCONN_JOIN((byte)0x32, "短连接设备请求接入"),
    CMD_DEV_SHORTCONN_IDVERIFY((byte)0x33, "短连接设备身份验证"),
    CMD_DEV_SHORTCONN_LOCATION((byte)0x34, "短连接设备位置信息上报"),
    CMD_DEV_SHORTCONN_TEMP_HUM_VOLTAGE((byte)0x35, "短连接设备温度、湿度和电量上报"),
    CMD_DEV_SHORTCONN_SMOG((byte)0x36, "短连接设备烟雾状态上报"),
    CMD_DEV_SHORTCONN_STATUS_QUERY((byte)0x37, "短连接设备状态信息查询"),
    CMD_DEV_SHORTCONN_TEMP_HUM_VOLTAGE_SET((byte)0x38, "短连接设备温度、湿度和电量上报频率预警值设置"),
    CMD_DEV_SHORTCONN_LOCATION_SET((byte)0x39, "短连接设备位置信息上报间隔设置"),
    CMD_DEV_SHORTCONN_SMOG_SET((byte)0x3A, "短连接烟雾状态上报间隔设置"),
    CMD_DEV_SHORTCONN_TEMP_ALARM((byte)0X3B, "短连接温度报警信息上传"),
    CMD_DEV_SHORTCONN_VOLTAGE_ALARM((byte)0x3C, "短连接电量报警信息上传"),
    CMD_DEV_SHORTCONN_HUM_SET((byte)0x3D, "短连接设备湿度信息设置"),
    CMD_DEV_SHORTCONN_HUM_ALARM((byte)0x3E, "短连接设备湿度报警"),
    CMD_DEV_SHORTCONN_RESET((byte)0x3F, "短连接设备复位信息上报"),
    CMD_DEV_SHORTCONN_UPLOAD_SET((byte)0xA1, "短连接图片上传时间设置"),
    CMD_DEV_SHORTCONN_UPLOAD_QUERY((byte)0xA2, "短连接图片上传时间查询"),
    CMD_DEV_SHORTCONN_UPLOAD_LAST((byte)0xA3, "短连接设备上传最近一次采集图片"),

    //图片上传相关指令
    CMD_DEV_UPLOAD_BALANCE((byte)0x01, "设备请求图片上传工作服务器"),
    CMD_DEV_UPLOAD_JOIN((byte)0x02, "设备接入图片上传服务器"),
    CMD_DEV_UPLOAD_PRE_REQUEST((byte)0x03, "请求上传图片"),
    CMD_DEV_UPLOAD_RESUME((byte)0x04, "上传图片数据"),
    CMD_DEV_UPLOAD_REUPLOAD((byte)0x05, "重新上传图片"),

    //websocket相关指令
    CMD_WEBSOCKET_JOIN((byte)0x00, "websocket服务器接入指令"),
    CMD_WEBSOCKET_HEARTBEAT((byte)0x01, "websocket服务器心跳指令");


    private byte cmd;//通信协议命令字

    private String chName;//命令释义

    public static Integer TYPE_NORMAL=0; //默认的基本命令字类型

    public static Integer TYPE_SHORT=1; //短连接模式命令字类型

    public static Integer TYPE_UPLOAD=2; //图片模式命令字类型

    public static Integer TYPE_WEBSOCKET=3; //websocket命令字类型

    CommandEnum(byte cmd, String chName) {
        this.cmd = cmd;
        this.chName = chName;
    }

    public byte getCmd () {
        return this.cmd;
    }

    public String getHexCmd () {
        return toHexString(this.cmd);
    }

    public String getChName() {
        return chName;
    }

    /**
     * 根据cmd的值获得一个CommandEnum实例
     * @param cmd
     * @return CommandEnum
     * @throws Exception
     */
    public static CommandEnum getCommandEnumByCmd(String cmd) throws Exception {
        byte cmdByte = ByteUtil.parseHexString(cmd);
        for (CommandEnum constant : CommandEnum.values()) {
            if (constant.getCmd() == cmdByte) {
                return constant;
            }
        }
        throw new Exception("Can't find the specific CommandEnum instance for input param : " + cmd);
    }

    /**
     * 根据cmd的值获得一个CommandEnum实例
     * @param cmd
     * @return
     * @throws Exception
     */
    public static CommandEnum getCommandEnumByCmd(byte cmd) throws Exception {
        for (CommandEnum constant : CommandEnum.values()) {
            if (constant.getCmd() == cmd) {
                return constant;
            }
        }
        throw new Exception("Can't find the specific CommandEnum instance for input param : " + cmd);
    }

    /**
     * 根据cmd的值和命令类型获得一个CommandEnum实例，
     * @param cmd
     * @param type 命令字类型
     * @return
     * @throws Exception
     */
    public static CommandEnum getCommandEnumByCmd(byte cmd, Integer type) throws Exception {
        for (CommandEnum constant : CommandEnum.values()) {
            switch (type) {
                case 0:
                    if (constant.ordinal() >= CMD_DEV_BALANCE.ordinal() &&
                            constant.ordinal() <= CMD_DEV_UPLOAD_LAST.ordinal()) {
                        if (constant.getCmd() == cmd) {
                            return constant;
                        }
                    }
                    break;
                case 1:
                    if (constant.ordinal() >= CMD_DEV_SHORTCONN_BALANCE.ordinal() &&
                            constant.ordinal() <= CMD_DEV_SHORTCONN_UPLOAD_LAST.ordinal()) {
                        if (constant.getCmd() == cmd) {
                            return constant;
                        }
                    }
                    break;
                case 2:
                    if (constant.ordinal() >= CMD_DEV_UPLOAD_BALANCE.ordinal() &&
                            constant.ordinal() <= CMD_DEV_UPLOAD_REUPLOAD.ordinal()) {
                        if (constant.getCmd() == cmd) {
                            return constant;
                        }
                    }
                    break;
                case 3:
                    if ((constant.ordinal() >= CMD_WEBSOCKET_JOIN.ordinal() &&
                            constant.ordinal() <= CMD_WEBSOCKET_HEARTBEAT.ordinal()) ||
                            (constant.ordinal() >= CMD_DEV_LOCATION.ordinal() &&
                            constant.ordinal() <= CMD_DEV_UPLOAD_LAST.ordinal())) {
                        if (constant.getCmd() == cmd) {
                            return constant;
                        }
                    }
                    break;
            }
        }
        throw new Exception("Can't find the specific CommandEnum instance for input param : " + cmd);
    }

    /**
     * 根据枚举名称获取一个CommandEnum实例
     * @param name
     * @return
     * @throws Exception
     */
    public static CommandEnum getCommandEnumByName (String name) throws Exception {
        return Enum.valueOf(CommandEnum.class, name);
    }

    /**
     * 根据枚举名称或cmd获取一个CommandEnum实例
     * @param param
     * @return
     * @throws Exception
     */
    public static CommandEnum getCommandEnum (String param) throws Exception {
        try {
            return getCommandEnumByName(param);
        } catch (Exception e) {
            return getCommandEnumByCmd(Integer.valueOf(param).byteValue());
        }
    }
    private String toHexString(byte b){
        String s = Integer.toHexString(b & 0xFF);
        int len = s.length();
        if(len < 2){
            s = "0" + s;
        }
        return s.toUpperCase();
    }
}
